package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.AlbumAttributeValueService;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private AlbumAttributeValueService albumAttributeValueService;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 更新声音播放量
     *
     * @param trackStatMqVo
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void trackStatUpdate(TrackStatMqVo trackStatMqVo) throws Exception {
        //	更新数据声音： update track_stat set stat_num = stat_num + 1 where track_id = 1 and stat_type = '0701';
        trackInfoMapper.trackStatUpdate(trackStatMqVo.getTrackId(), trackStatMqVo.getStatType(), trackStatMqVo.getCount());
        //	更新专辑：
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
            //	调用更新专辑播放量方法.
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY, trackStatMqVo.getCount());
        }
    }

    @Override
    @GuiGuCache(prefix = "stat:")
    public AlbumStatVo getAlbumStatVo(Long albumId) {
        //	调用mapper
        return albumInfoMapper.selectAlbumStatVo(albumId);
    }

    @Override
    public List<AlbumAttributeValue> findAlbumAttributeValue(Long albumId) {
		/*
		select
			attribute_id,
			value_id
		from album_attribute_value
		where album_id = ? and is_deleted = 0
		 */
        //	使用mapper 的时候默认给我们添加is_delete = 0;
        return albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
    }

    @Override
    public List<AlbumInfo> findUserAllAlbumList(Long userId) {
        //	根据用户Id 查询专辑列表
        //	List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(new LambdaQueryWrapper<AlbumInfo>().eq(AlbumInfo::getUserId, userId));
        //	Page<AlbumInfo> albumInfoPage = new Page<>(1,20);
        //	select id, album_title from album_info where user_id = ? order by id desc limit 0,20;

        //		LambdaQueryWrapper<AlbumInfo> wrapper = new LambdaQueryWrapper<AlbumInfo>()
        //				.eq(AlbumInfo::getUserId, userId)
        //				.select(AlbumInfo::getId,AlbumInfo::getAlbumTitle)
        //				.orderByDesc(AlbumInfo::getId);
        //		//	查询数据
        //		Page<AlbumInfo> selectPage = albumInfoMapper.selectPage(albumInfoPage, wrapper);
        //		return selectPage.getRecords();
        //	select id, album_title from album_info where user_id = ? order by id desc limit 20;
        LambdaQueryWrapper<AlbumInfo> wrapper = new LambdaQueryWrapper<AlbumInfo>()
                .eq(AlbumInfo::getUserId, userId)
                .select(AlbumInfo::getId, AlbumInfo::getAlbumTitle)
                .orderByDesc(AlbumInfo::getId)
                .last(" limit 20 ");
        //	返回数据
        return albumInfoMapper.selectList(wrapper);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
        //	修改简介相当于改 album_info
        //	第一个参数表示要修改的内容，第二个参数表示修改的条件
        //  albumInfoMapper.update();
        //	第一个参数表示修改的内容+条件{主键Id}
        AlbumInfo albumInfo = new AlbumInfo();
        //	给albumInfo 赋值
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        albumInfo.setId(albumId);
        albumInfoMapper.updateById(albumInfo);

        //	修改标签相当于改 album_attribute_value
        //	先删除，再新增.
        //	delete from album_attribute_value where album_id = ?; 物理删除
        //	update album_attribute_value set is_deleted = 1 where album_id = ?; 逻辑删除
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));

        //  album_attribute_value
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //	判断
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
            //	循环遍历。
            List<AlbumAttributeValue> attributeValueList = albumAttributeValueVoList.stream().map(albumAttributeValueVo -> {
                //	创建对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                //	赋值
                albumAttributeValue.setAlbumId(albumInfo.getId());
                albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
                albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
                //	返回对象
                return albumAttributeValue;
            }).collect(Collectors.toList());

            //	批量保存：albumAttributeValueMapper  album_attribute_value
            //	利用mybatis-plus 中IService ServiceIMpl 这个类处理！
            albumAttributeValueService.saveBatch(attributeValueList);
        }

        //	判断是否上架：
        if ("1".equals(albumInfoVo.getIsOpen())) {
            //	上架
            kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_UPPER, albumId.toString());
        } else {
            //	下架
            kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_LOWER, albumId.toString());
        }

    }

    @Override
    @GuiGuCache(prefix = "album:")
    //  分布式锁的key album:albumId:lock 保证key 唯一：前缀：参数：后缀
    public AlbumInfo getAlbumInfoById(Long albumId) {
        //        AlbumInfo albumInfo = getAlbumInfoByRedisson(albumId);
        //        if (albumInfo != null) return albumInfo;
        //	查询数据库
        return getAlbumInfoDB(albumId);
    }

    @Nullable
    private AlbumInfo getAlbumInfoByRedisson(Long albumId) {
        //	查询缓存：String set key value;
        String key = RedisConstant.ALBUM_INFO_PREFIX + albumId;
        //        Boolean result = redisTemplate.opsForValue().setBit(key, albumId, true);
        //        if (result){
        //
        //        }
        //        //  删除
        //        redisTemplate.opsForValue().setBit(key,albumId,false);
        //  从缓存中获取数据
        try {
            AlbumInfo albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(key);
            //  判断当前专辑对象是否为空
            if (null == albumInfo) {
                //  缓存中没有数据，查询数据库，避免缓存击穿要加分布式锁！
                //  声明一个锁的key
                String lockKey = RedisConstant.ALBUM_LOCK_SUFFIX + albumId;
                RLock lock = redissonClient.getLock(lockKey);
                //  如何lock加锁！
                lock.lock();
                //  执行业务逻辑。
                try {
                    //  获取到锁的时候，最好再查询一次缓存。
                    albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(key);
                    log.info("查询了缓存....");
                    if (null != albumInfo) {
                        return albumInfo;
                    }
                    //  查询数据库
                    albumInfo = getAlbumInfoDB(albumId);
                    //  判断当前这个对象是否存在.
                    if (null == albumInfo) {
                        //  返回数据
                        this.redisTemplate.opsForValue().set(key, new AlbumInfo(), RedisConstant.ALBUM_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
                        //  返回空对象
                        return new AlbumInfo();
                    } else {
                        //  数据库中有数据
                        this.redisTemplate.opsForValue().set(key, albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS);
                        return albumInfo;
                    }
                } finally {
                    //  解锁
                    lock.unlock();
                }
            } else {
                return albumInfo;
            }
        } catch (Exception e) {
            log.error("出现了异常{}专辑Id：\t", albumId);
            //  调用sendMsg(phoneNumber);
            e.printStackTrace();
        }
        return null;
    }

    //	查询数据库.
    @Nullable
    private AlbumInfo getAlbumInfoDB(Long albumId) {
        //	先获取到专辑信息表数据 album_info
        //  select * from album_info where id = ? and is_deleted = 0;
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //	获取到 专辑属性与属性值数据集合.
        if (null != albumInfo) {
            //	想办法获取到属性与属性值集合数据.
            //	根据 album_id 查询 album_attribute_value 集合.
            //  select * from album_attribute_value where album_id = ?;
            List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
            albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
        }
        //	返回对象数据
        return albumInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAlbumInfo(Long albumId) {
		/*
		album_attribute_value
		album_info
		album_stat
		 */
        //	删除：逻辑删除 update album_info set is_deleted = ? where id = ?
        //	物理删除 delete from album_info where album_id = ?
        albumInfoMapper.deleteById(albumId); // 逻辑删除

        //	where album_id = ?;
        albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, albumId));
        //	delete from album_stat where album_id = ?;
        //	albumStatMapper.deleteByAlbumId(albumId);

        //	album_attribute_value; album_id = ?;
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));

    }

    @Override
    public IPage<AlbumListVo> getUserAlbumPage(Page<AlbumListVo> albumListVoPage, AlbumInfoQuery albumInfoQuery) {
        //	根据业务分析：需要 album_info album_stat
        return albumInfoMapper.selectUserAlbumPage(albumListVoPage, albumInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
        //	album_info
        try {
            //	创建专辑对象
            AlbumInfo albumInfo = new AlbumInfo();
            //	进行属性拷贝
            BeanUtils.copyProperties(albumInfoVo, albumInfo);
            albumInfo.setUserId(userId);
            albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
            //	设置免费的集数.
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())) {
                //	只要收费就设置前5集为免费试听集数
                albumInfo.setTracksForFree(5);
            }
            //	当执行插入完成之后，获取到专辑Id
            //	在实体类id属性上 @TableId(type = IdType.AUTO) 表示插入完成之后能够自动获取到主键自增的Id.
            albumInfoMapper.insert(albumInfo);

            //  album_attribute_value
            List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
            //	判断
            if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
                //	声明一个集合
                //				List<AlbumAttributeValue> attributeValueList = new ArrayList<>();
                //				//	循环遍历这个集合保存数据.
                //				for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
                //					//	创建一个专辑对应的属性与属性值对象
                //					AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                //					albumAttributeValue.setAlbumId(albumInfo.getId());
                //					albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
                //					albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
                //					// albumAttributeValueMapper.insert(albumAttributeValue);
                //					attributeValueList.add(albumAttributeValue);
                //				}
                //
                List<AlbumAttributeValue> attributeValueList = albumAttributeValueVoList.stream().map(albumAttributeValueVo -> {
                    //	创建对象
                    AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                    //	赋值
                    albumAttributeValue.setAlbumId(albumInfo.getId());
                    albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
                    albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
                    //	返回对象
                    return albumAttributeValue;
                }).collect(Collectors.toList());

                //	批量保存：albumAttributeValueMapper  album_attribute_value
                //	利用mybatis-plus 中IService ServiceIMpl 这个类处理！
                albumAttributeValueService.saveBatch(attributeValueList);

            }

            //	album_stat
            this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
            this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
            this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
            this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);

            //	发送上架消息
            if ("1".equals(albumInfo.getIsOpen())) {
                this.kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_UPPER, String.valueOf(albumInfo.getId()));
            }


        } catch (BeansException e) {
            log.error("保存专辑失败");
            throw new RuntimeException(e);
        }



    }

    public void saveAlbumStat(Long albumId, String statPlay) {
        //	创建统计对象
        AlbumStat albumStat = new AlbumStat();
        albumStat.setAlbumId(albumId);
        albumStat.setStatType(statPlay);
        albumStat.setStatNum(0);
        albumStatMapper.insert(albumStat);
    }
}
